﻿using System;
using System.Collections.Generic;
using System.Text;
using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Faceid.V20180301;
using TencentCloud.Faceid.V20180301.Models;
using Infrastructure.Error;
using Utility;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using Infrastructure.Config;
using System.Linq;

namespace OtherLib.TenXun
{
    public static class FaceIDUtil
    {
        static readonly string FACE_ID;
        static readonly string FACE_SECRET;
        static FaceIDUtil()
        {
            var aliSmsConfig = ApplicationConfig.GetConfig().GetSection("TenXunFaceID");

            FACE_ID = aliSmsConfig["ID"];
            FACE_SECRET = aliSmsConfig["Secret"];
        }

        private static object at_lock = new object();
        private static string AccessToken = string.Empty;
        private static DateTime AccessTokenOutTime;

        private static string GetAccessToken()
        {
            try
            {
                if (AccessTokenOutTime > DateTime.Now) return AccessToken;

                lock (at_lock)
                {
                    if (AccessTokenOutTime > DateTime.Now) return AccessToken;

                    var url = $"https://idasc.webank.com/api/oauth2/access_token?app_id={FACE_ID}&secret={FACE_SECRET}&grant_type=client_credential&version=1.0.0";

                    var r = HttpUtil.GetText(url).GetAwaiter().GetResult();
                    if (string.IsNullOrWhiteSpace(r)) throw new BizException("FaceID AccessToken 获取为空");

                    var jObject = (JObject)JsonConvert.DeserializeObject(r);

                    if (jObject.Value<int>("code") == 0)
                    {
                        AccessToken = jObject.Value<string>("access_token");
                        AccessTokenOutTime = DateTime.Now.AddSeconds(jObject.Value<int>("expire_in") - 1000);

                        return AccessToken;
                    }
                    Console.WriteLine("GetAccessToken Error:" + r);
                    throw new BizException(jObject.Value<string>("msg"));
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                throw e;
            }
        }

        public static string GetTicket(string uid,string type= "NONCE")
        {
            try
            {
                var url = $"https://idasc.webank.com/api/oauth2/api_ticket?app_id={FACE_ID}&access_token={GetAccessToken()}&type={type}&version=1.0.0&user_id={uid}";

                var r = HttpUtil.GetText(url).GetAwaiter().GetResult();

                if (string.IsNullOrWhiteSpace(r)) throw new BizException("FaceID Ticket 获取为空");

                var jObject = (JObject)JsonConvert.DeserializeObject(r);

                if (jObject.Value<int>("code") == 0)
                {
                    var first = jObject["tickets"].First;
                    return first.Value<string>("value");
                }
                Console.WriteLine("GetTicket Error:" + r);
                throw new BizException(jObject.Value<string>("msg"));

            }
            catch (BizException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static string MakeTicketSign(string userID, string nonceStr, string ticket, string version = "1.0.0")
        {
            List<string> list = new List<string>();
            list.Add(FACE_ID);
            list.Add(userID);
            list.Add(nonceStr);
            list.Add(ticket);
            list.Add(version);

            return MakeSign(list);
        }
        public static string MakeResultSign(string order_no, string version, string ticket, string nonceStr)
        {
            List<string> list = new List<string>();
            list.Add(FACE_ID);
            list.Add(order_no);
            list.Add(nonceStr);
            list.Add(ticket);
            list.Add(version);

            return MakeSign(list);
        }
        public static async Task<string> GetFaceID(string orderNo, string name, string idNo, string userId, string sign, string version = "1.0.0", string sourcePhotoType = null, string sourcePhotoStr = null)
        {
            const string url = "https://idasc.webank.com/api/server/getfaceid";

            Dictionary<string, string> map = new Dictionary<string, string>();
            map.Add("webankAppId", FACE_ID);
            map.Add("orderNo", orderNo);
            map.Add("name", name);
            map.Add("idNo", idNo);
            map.Add("userId", userId);
            map.Add("version", version);
            map.Add("sign", sign);

            if (!string.IsNullOrWhiteSpace(sourcePhotoStr))
            {
                map.Add("sourcePhotoType", sourcePhotoType);
                map.Add("sourcePhotoStr", sourcePhotoStr);
            }
            
            try
            {
                var r = await HttpUtil.PostJson(url, JsonConvert.SerializeObject(map));
                if (string.IsNullOrWhiteSpace(r)) throw new BizException("FaceID FaceID 获取为空");
                var jObject = (JObject)JsonConvert.DeserializeObject(r);

                if (jObject.Value<int>("code") == 0)
                {
                    return jObject["result"].Value<string>("faceId");
                }
                Console.WriteLine("GetFaceID Error:" + r);
                throw new BizException(jObject.Value<string>("msg"));

            }
            catch (BizException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                throw e;
            }
        }


        public static async Task<string> GetFaceResult(string orderNo, string nonceStr, string sign, string version = "1.0.0")
        {
            var url = $"https://idasc.webank.com/api/server/sync?app_id={FACE_ID}&nonce={nonceStr}&order_no={orderNo}&version={version}&sign={sign}&get_file=1";
            Console.WriteLine("GetFaceResult Url:" + url);
            try
            {
                var r = await HttpUtil.GetText(url);
                if (string.IsNullOrWhiteSpace(r)) throw new BizException("FaceID Result 获取为空");
                Console.WriteLine("GetFaceResult Json:" + r);
                var jObject = (JObject)JsonConvert.DeserializeObject(r);

                if (jObject.Value<int>("code") == 0)
                {
                    return r;
                }

                Console.WriteLine("GetFaceResult Error:" + r);

                throw new BizException(jObject.Value<string>("msg"),dic=> {
                    dic.Add("data", r);
                });

            }
            catch (BizException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                throw e;
            }
        }

        private static string MakeSign(List<string> list)
        {
            list = list.OrderBy(o => o, StringComparer.Ordinal).ToList();
            StringBuilder sb = new StringBuilder();

            StringBuilder sb1 = new StringBuilder();
            foreach (var item in list)
            {
                sb.Append(item);
                sb1.Append(item);
                sb1.Append(",");
            }
            Console.WriteLine("FaceID排序:" + sb1.ToString());

            return Sha1Util.Encryptor(sb.ToString());
        }


    }
}
